
#include "fft.h"
#ifdef SIZE
#undef SIZE
#endif
#include <ap_int.h>
#include <hls_stream.h>
#include <cstring>

using hls::stream;

const int FFTSIZE=1024; 		/* FFTSIZE OF FFT */
const int RAM_PART_FCT=32;     // ram partition factor
const int RAM_PART_FCT2 = 1;   // another ram partition factor -_-|
const int FIFO_D=3;            // fifo depth
const int MYDTYPEW = 32;       // MYDTYPE 位宽
const int MYDTYPEFW = 8;       // MYDTYPEFW 小数位位宽

typedef ap_fixed<17, 2> WTYPE; // 旋转因子数据类型
typedef ap_fixed<MYDTYPEW, MYDTYPEW-MYDTYPEFW> MYDTYPE; // 内部计算数据类型

struct cplx {
	MYDTYPE r;
	MYDTYPE i;
};

union f_cast {
	DTYPE f;
	unsigned int i;
};

// float -> fixed
inline MYDTYPE DTYPE2MYDTYPE(const DTYPE & dtype) {
#pragma HLS INLINE
	f_cast db2uint;
	db2uint.f = dtype;
	ap_uint<32> float_tmp = db2uint.i;

	ap_int<9> exp = float_tmp(30, 23);
#pragma HLS BIND_OP variable=exp op=sub impl=fabric latency=1
#pragma HLS BIND_OP variable=exp op=add impl=fabric latency=1
	exp = 150 - exp - MYDTYPEFW;
	MYDTYPE fix_tmp = 0;
#pragma HLS BIND_OP variable=fix_tmp op=sub impl=fabric latency=1
	fix_tmp[23] = 1;
	fix_tmp(22,0) = float_tmp(22, 0);

	fix_tmp >>= (exp);
//	ap_uint<1> exp_sign = exp[8];
//	if(exp_sign) {
//		exp = -exp;
//		fix_tmp >>= exp;
//	}
//	else {
//		fix_tmp <<= exp;
//	}

	if(float_tmp[31])
		fix_tmp = -fix_tmp;

	return fix_tmp;
}

// fixed -> float
inline DTYPE MYDTYPE2DTYPE(const MYDTYPE mydtype)
{
//#pragma HLS latency min=5
	MYDTYPE abs = mydtype;
#pragma HLS BIND_OP variable=abs op=sub impl=fabric latency=1
	if(mydtype[31])
		abs = -abs;

	ap_int<8> highest_bit = -1;
	for(int n = 30; n >= MYDTYPEFW; n--) {
#pragma HLS UNROLL
		if(abs[n] == 1) {
			highest_bit = n;
			break;
		}
	}

	ap_int<9> exp = highest_bit - MYDTYPEFW + 127;
#pragma HLS BIND_OP variable=exp op=sub impl=fabric latency=1
#pragma HLS BIND_OP variable=exp op=add impl=fabric latency=1
	ap_uint<32> float_tmp=0;
	float_tmp[31] = mydtype[31];
	float_tmp(30, 23) = exp(7,0);
	int low_bits_1 = 0;
	int low_bits_2 = 0;
#pragma HLS BIND_OP variable=low_bits_1 op=sub impl=fabric latency=1
#pragma HLS BIND_OP variable=low_bits_2 op=sub impl=fabric latency=1
	ap_int<8> shfit_num = 23-highest_bit;
#pragma HLS BIND_OP variable=shfit_num op=sub impl=fabric latency=1



	ap_int<8> abs_hight = highest_bit-1;
#pragma HLS BIND_OP variable=abs_hight op=sub impl=fabric latency=1

	abs <<= shfit_num;

	float_tmp(22,0) = abs(22,0);


//	float_tmp(22, low_bits_1) = abs(abs_hight, low_bits_2);

	f_cast cast;
//	if(highest_bit[7] == 0)
//
//	else
//		cast.i = 0;
	cast.i = float_tmp(31,0);
	return cast.f;

}


void bit_reverse(ap_uint<1024> XR[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT],
		ap_uint<1024> XI[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT],
		DTYPE OUT_R[FFTSIZE], DTYPE OUT_I[FFTSIZE]) {

	ap_uint<4> tmp;
	ap_uint<6> tmp2;

	ap_uint<1024> xout[RAM_PART_FCT];
	ap_uint<1024> xiout[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=xout dim=1 complete
#pragma HLS ARRAY_PARTITION variable=xiout dim=1 complete

	MYDTYPE outr_buffer[RAM_PART_FCT];
	MYDTYPE outi_buffer[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=outr_buffer dim=1 complete
#pragma HLS ARRAY_PARTITION variable=outi_buffer dim=1 complete

//	f_cast cast;
	char data_str[64];

for(int i = 0; i < 32; i++) {
#pragma HLS PIPELINE ii=1

	ap_uint<5> addr1 = i;
	addr1.reverse();

//	ap_uint<1> addr2 = addr1(5,5);

	for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL
		ap_uint<5> out_addr_lowbits = n;
		out_addr_lowbits.reverse();
		xout[n] = XR[out_addr_lowbits][0];
		xiout[n] = XI[out_addr_lowbits][0];
	}

	ap_uint<5> offset = addr1(4,0);
	for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL
		MYDTYPE xout_tmp;
		xout_tmp(31,0) = xout[n](offset*32+31, offset*32);
		outr_buffer[n] = xout_tmp;

//		sprintf(data_str, "%s", xout_tmp.to_string(2).c_str());

		MYDTYPE xiout_tmp;
		xiout_tmp(31,0) = xiout[n](offset*32+31, offset*32);
		outi_buffer[n] = xiout_tmp;
	}


	for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL

		OUT_R[i*RAM_PART_FCT+n] = MYDTYPE2DTYPE(outr_buffer[n]);
		OUT_I[i*RAM_PART_FCT+n] = MYDTYPE2DTYPE(outi_buffer[n]);
	}

}


}

void out(MYDTYPE XR[FFTSIZE], MYDTYPE XI[FFTSIZE], DTYPE OUT_R[FFTSIZE], DTYPE OUT_I[FFTSIZE]) {

	for(int i = 0; i < FFTSIZE; i++) {

//		f_cast cast;
//		cast.i = XR[i](31,0);
//		OUT_R[i] = cast.f;
//		OUT_I[i] = cast.f;

		OUT_R[i] = MYDTYPE2DTYPE(XR[i]);

		float xr_tmp = XR[i].to_float();
		float outr_tmp = OUT_R[i];

		OUT_I[i] = MYDTYPE2DTYPE(XI[i]);
	}
}

inline void r4_butterfly(MYDTYPE x0r,MYDTYPE x0i,MYDTYPE x1r, MYDTYPE x1i, MYDTYPE x2r, MYDTYPE x2i, MYDTYPE x3r, MYDTYPE x3i,
		WTYPE w1r, WTYPE w1i, WTYPE w2r, WTYPE w2i, WTYPE w3r, WTYPE w3i,
						MYDTYPE &y0r,MYDTYPE &y0i,MYDTYPE &y1r, MYDTYPE &y1i, MYDTYPE &y2r, MYDTYPE &y2i, MYDTYPE &y3r, MYDTYPE &y3i) {
#pragma HLS INLINE

	MYDTYPE x3wr = x3r * w3r - x3i * w3i;
	MYDTYPE x3wi = x3i * w3r + x3r * w3i;
	MYDTYPE x2wr = x2r * w2r - x2i * w2i;
	MYDTYPE x2wi = x2i * w2r + x3r * w2i;
	MYDTYPE x1wr = x1r * w1r - x1i * w1i;
	MYDTYPE x1wi = x1i * w1r + x1r * w1i;

	y0r = (x0r + x1wr) + (x2wr + x3wr);
	y1r = (x0r - x1wi) - (x2wr - x3wi);  // [1 j -1 -j]
	y2r = (x0r - x1wr) + (x2wr - x3wr); //[1 -1 1 -1]
	y3r = (x0r + x1wr) - (x2wr + x3wi); //[1 -j -1 j]

	y0i = (x0i + x1wi) + (x2wi + x3wi);
	y1i = (x0i + x1wr) - (x2wi + x3wr);  // [1 j -1 -j]
	y2i = (x0i - x1wi) + (x2wi - x3wi); //[1 -1 1 -1]
	y3i = (x0i - x1wr) - (x2wi - x3wr); //[1 -j -1 j]
}

// 基4 频率抽取  butterfly单元
inline void r4_dif_butterfly(
		MYDTYPE xr[4][RAM_PART_FCT], MYDTYPE xi[4][RAM_PART_FCT],
		WTYPE wr[3][RAM_PART_FCT], WTYPE wi[3][RAM_PART_FCT],
		MYDTYPE yr[4][RAM_PART_FCT], MYDTYPE yi[4][RAM_PART_FCT]) {
#pragma HLS INLINE

	for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL

		MYDTYPE ytmp;
#pragma HLS BIND_OP variable=ytmp op=add latency=1
#pragma HLS BIND_OP variable=ytmp op=sub latency=1
#pragma HLS BIND_OP variable=ytmp op=mul latency=1

		ytmp= (xr[0][n] + xr[1][n]) + (xr[2][n] + xr[3][n]);
		yr[0][n]= ytmp;

		ytmp= (xr[0][n] - xr[1][n]) + (xr[2][n] - xr[3][n]);
		MYDTYPE yr1_tmp = ytmp;

		ytmp= (xr[0][n] + xi[1][n]) - (xr[2][n] + xi[3][n]);
		MYDTYPE yr2_tmp = ytmp;

		ytmp= (xr[0][n] - xi[1][n]) - (xr[2][n] - xi[3][n]);
		MYDTYPE yr3_tmp = ytmp;

	    ytmp= (xi[0][n] + xi[1][n]) + (xi[2][n] + xi[3][n]);
	    yi[0][n]= ytmp;
		ytmp= (xi[0][n] - xi[1][n]) + (xi[2][n] - xi[3][n]);
		MYDTYPE yi1_tmp = ytmp;
		ytmp= (xi[0][n] - xr[1][n]) - (xi[2][n] - xr[3][n]);
		MYDTYPE yi2_tmp = ytmp;
		ytmp= (xi[0][n] + xr[1][n]) - (xi[2][n] + xr[3][n]);
		MYDTYPE yi3_tmp = ytmp;


		ytmp = yr1_tmp * wr[0][n] - yi1_tmp * wi[0][n];
		yr[1][n] = ytmp;

		ytmp = yr1_tmp * wi[0][n] + yi1_tmp * wr[0][n];
		yi[1][n] = ytmp;

		ytmp = yr2_tmp * wr[1][n] - yi2_tmp * wi[1][n];
		yr[2][n] = ytmp;

		ytmp = yr2_tmp * wi[1][n] + yi2_tmp * wr[1][n];
		yi[2][n] = ytmp;

		ytmp = yr3_tmp * wr[2][n] - yi3_tmp * wi[2][n];
		yr[3][n] = ytmp;

		ytmp = yr3_tmp * wi[2][n] + yi3_tmp * wr[2][n];
		yi[3][n] = ytmp;

	}


}

inline void r4_dif_butterfly(MYDTYPE x0r,MYDTYPE x0i,MYDTYPE x1r, MYDTYPE x1i, MYDTYPE x2r, MYDTYPE x2i, MYDTYPE x3r, MYDTYPE x3i,
		WTYPE w1r, WTYPE w1i, WTYPE w2r, WTYPE w2i, WTYPE w3r, WTYPE w3i,
MYDTYPE &y0r,MYDTYPE &y0i,MYDTYPE &y1r, MYDTYPE &y1i, MYDTYPE &y2r, MYDTYPE &y2i, MYDTYPE &y3r, MYDTYPE &y3i) {

	MYDTYPE ytmp;
#pragma HLS BIND_OP variable=ytmp op=add latency=1
#pragma HLS BIND_OP variable=ytmp op=sub latency=1
#pragma HLS BIND_OP variable=ytmp op=mul latency=1

ytmp= (x0r + x1r) + (x2r + x3r);
y0r = ytmp;
ytmp= (x0r - x1r) + (x2r - x3r);
MYDTYPE yr1_tmp = ytmp;
ytmp= (x0r + x1i) - (x2r + x3i);
MYDTYPE yr2_tmp = ytmp;
ytmp= (x0r - x1i) - (x2r - x3i);
MYDTYPE yr3_tmp = ytmp;

    ytmp= (x0i + x1i) + (x2i + x3i);
    y0i = ytmp;
ytmp= (x0i - x1i) + (x2i - x3i);
MYDTYPE yi1_tmp = ytmp;
ytmp= (x0i - x1r) - (x2i - x3r);
MYDTYPE yi2_tmp = ytmp;
ytmp= (x0i + x1r) - (x2i + x3r);
MYDTYPE yi3_tmp = ytmp;


ytmp = yr1_tmp * w1r - yi1_tmp * w1i;
y1r = ytmp;
ytmp = yr1_tmp * w1i + yi1_tmp * w1r;
y1i = ytmp;

ytmp = yr2_tmp * w2r - yi2_tmp * w2i;
y2r = ytmp;
ytmp = yr2_tmp * w2i + yi2_tmp * w2r;
y2i = ytmp;

ytmp = yr3_tmp * w3r - yi3_tmp * w3i;
y3r = ytmp;
ytmp = yr3_tmp * w3i + yi3_tmp * w3r;
y3i = ytmp;

}


inline void fft_4point(MYDTYPE x0r,MYDTYPE x0i,MYDTYPE x1r, MYDTYPE x1i, MYDTYPE x2r, MYDTYPE x2i, MYDTYPE x3r, MYDTYPE x3i,
MYDTYPE &y0r,MYDTYPE &y0i,MYDTYPE &y1r, MYDTYPE &y1i, MYDTYPE &y2r, MYDTYPE &y2i, MYDTYPE &y3r, MYDTYPE &y3i) {


	MYDTYPE ytmp;
#pragma HLS BIND_OP variable=ytmp op=add latency=1
#pragma HLS BIND_OP variable=ytmp op=sub latency=1
#pragma HLS BIND_OP variable=ytmp op=mul latency=1

ytmp= (x0r + x1r) + (x2r + x3r);
y0r = ytmp;
ytmp= (x0r - x1r) + (x2r - x3r);
y1r =ytmp;
ytmp= (x0r + x1i) - (x2r + x3i);
y2r =ytmp;
ytmp= (x0r - x1i) - (x2r - x3i);
y3r =ytmp;

ytmp= (x0i + x1i) + (x2i + x3i);
y0i =ytmp;
ytmp= (x0i - x1i) + (x2i - x3i);
y1i =ytmp;
ytmp= (x0i - x1r) - (x2i - x3r);
y2i =ytmp;
ytmp= (x0i + x1r) - (x2i + x3r);
y3i =ytmp;



}

void fft_5(stream<ap_uint<1024>> X_R[RAM_PART_FCT2],
		stream<ap_uint<1024>> X_I[RAM_PART_FCT2],
		ap_uint<1024> DOUTR[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT],
		ap_uint<1024> DOUTI[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT])
{

	MYDTYPE xr[RAM_PART_FCT], xi[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=xr dim=1 complete
#pragma HLS ARRAY_PARTITION variable=xi dim=1 complete
	MYDTYPE y[RAM_PART_FCT], yi[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=y dim=1 complete
#pragma HLS ARRAY_PARTITION variable=yi dim=1 complete

	ap_uint<1024> tmpr;
	ap_uint<1024> tmpi;

	int ram_id=0, addr=0;

	// 循环32次，每次8个butterfly
	for(int i = 0; i < FFTSIZE/RAM_PART_FCT2; i+=RAM_PART_FCT) {
		for(int m = 0; m < RAM_PART_FCT2; m++) {
#pragma HLS UNROLL

			ap_uint<1024> xr_tmp = X_R[m].read();
			ap_uint<1024> xi_tmp = X_I[m].read();

			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				xr[n](31,0) = xr_tmp(n*32+31, n*32);
				xi[n](31,0) = xi_tmp(n*32+31, n*32);
			}

			// 每相邻4个数做
			for(int j = 0; j < 8; j++) {
	#pragma HLS UNROLL
				fft_4point(xr[0+4*j], xi[0+4*j], xr[1+4*j], xi[1+4*j], xr[2+4*j], xi[2+4*j], xr[3+4*j], xi[3+4*j],
						y[0+4*j], yi[0+4*j], y[1+4*j], yi[1+4*j], y[2+4*j], yi[2+4*j], y[3+4*j], yi[3+4*j]);
			}

			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
	//			cast.f = y[n];
	//			cast.f = xr[n];
				tmpr(n*32+31, n*32) = y[n](31,0);
				float y_flt = y[n].to_float();
	//			cast.f = yi[n];
	//			cast.f = xi[n];
				tmpi(n*32+31, n*32) = yi[n](31,0);
			}

			DOUTR[m*RAM_PART_FCT/RAM_PART_FCT2 + ram_id][addr] = tmpr;
			DOUTI[m*RAM_PART_FCT/RAM_PART_FCT2 + ram_id][addr] = tmpi;

		}
		addr++;
		if(addr==FFTSIZE/RAM_PART_FCT/RAM_PART_FCT) {
			addr = 0;
			ram_id++;
		}
	}

}

// butterfly stride 4
void fft_4(stream<ap_uint<1024>, 4> X_R[RAM_PART_FCT2],
		stream<ap_uint<1024>, 4> X_I[RAM_PART_FCT2],
		stream<ap_uint<1024>> DOUTR[RAM_PART_FCT2],
		stream<ap_uint<1024>> DOUTI[RAM_PART_FCT2]) {

	static const WTYPE WR[12]={1.000000000000000000e+00,7.071067811865475727e-01,6.123233995736766036e-17,-7.071067811865474617e-01,1.000000000000000000e+00,9.238795325112867385e-01,7.071067811865475727e-01,3.826834323650898373e-01,1.000000000000000000e+00,3.826834323650898373e-01,-7.071067811865474617e-01,-9.238795325112868495e-01};
	static const WTYPE WI[12]={-0.000000000000000000e+00,-7.071067811865474617e-01,-1.000000000000000000e+00,-7.071067811865475727e-01,-0.000000000000000000e+00,-3.826834323650897818e-01,-7.071067811865474617e-01,-9.238795325112867385e-01,-0.000000000000000000e+00,-9.238795325112867385e-01,-7.071067811865475727e-01,3.826834323650896708e-01};
#pragma HLS ARRAY_PARTITION variable=WR dim=1 complete
#pragma HLS ARRAY_PARTITION variable=WI dim=1 complete


	MYDTYPE xr[RAM_PART_FCT], xi[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=xr dim=1 complete
#pragma HLS ARRAY_PARTITION variable=xi dim=1 complete

	MYDTYPE y[RAM_PART_FCT], yi[RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=y dim=1 complete
#pragma HLS ARRAY_PARTITION variable=yi dim=1 complete

	// 循环32次，每次8个butterfly
	for(int i = 0; i < FFTSIZE/RAM_PART_FCT2; i+=RAM_PART_FCT) {
#pragma HLS PIPELINE ii=1
		for(int m = 0; m < RAM_PART_FCT2; m++) {
#pragma HLS UNROLL
			ap_uint<1024> xr_tmp = X_R[m].read();
			ap_uint<1024> xi_tmp = X_I[m].read();
			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				xr[n](31,0) = xr_tmp(32*n+31, 32*n);
				xi[n](31,0) = xi_tmp(32*n+31, 32*n);
			}

			// 前16个数据做4个蝶形计算
			for(int j = 0; j < 4; j++) {
	#pragma HLS UNROLL
				r4_dif_butterfly(xr[0+j], xi[0+j], xr[4+j], xi[4+j], xr[8+j], xi[8+j], xr[12+j], xi[12+j],
						WR[0+j], WI[0+j], WR[4+j], WI[4+j], WR[8+j], WI[8+j],
						y[0+j], yi[0+j], y[4+j], yi[4+j], y[8+j], yi[8+j], y[12+j], yi[12+j]);
			}

			// 后16个数做4个蝶形计算
			for(int j = 0; j < 4; j++) {
	#pragma HLS UNROLL
				r4_dif_butterfly(xr[16+j], xi[16+j], xr[16+4+j], xi[16+4+j], xr[16+8+j], xi[16+8+j], xr[16+12+j], xi[16+12+j],
						WR[0+j], WI[0+j], WR[4+j], WI[4+j], WR[8+j], WI[8+j],
						y[16+0+j], yi[16+0+j], y[16+4+j], yi[16+4+j], y[16+8+j], yi[16+8+j], y[16+12+j], yi[16+12+j]);
			}

			// 输出聚合为1024 bits
			ap_uint<1024> dout_tmp;
			ap_uint<1024> douti_tmp;
			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				dout_tmp(n*32+31, n*32) = y[n](31,0);
			}
			DOUTR[m].write(dout_tmp);

			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				douti_tmp(n*32+31, n*32) = yi[n](31,0);
			}
			DOUTI[m].write(douti_tmp);

		}
	}

}

// butterfly stride 16
void fft_3(MYDTYPE X_R[FFTSIZE], MYDTYPE X_I[FFTSIZE],
		stream<ap_uint<1024>, 4> DOUTR[RAM_PART_FCT2],
		stream<ap_uint<1024>, 4> DOUTI[RAM_PART_FCT2]) {

	static const WTYPE WR[48]={1.000000000000000000e+00,9.807852804032304306e-01,9.238795325112867385e-01,8.314696123025452357e-01,7.071067811865475727e-01,5.555702330196022887e-01,3.826834323650898373e-01,1.950903220161283314e-01,6.123233995736766036e-17,-1.950903220161281926e-01,-3.826834323650897263e-01,-5.555702330196019556e-01,-7.071067811865474617e-01,-8.314696123025453467e-01,-9.238795325112867385e-01,-9.807852804032304306e-01,1.000000000000000000e+00,9.951847266721969287e-01,9.807852804032304306e-01,9.569403357322088244e-01,9.238795325112867385e-01,8.819212643483550496e-01,8.314696123025452357e-01,7.730104533627369934e-01,7.071067811865475727e-01,6.343932841636454878e-01,5.555702330196022887e-01,4.713967368259978086e-01,3.826834323650898373e-01,2.902846772544623311e-01,1.950903220161283314e-01,9.801714032956077016e-02,1.000000000000000000e+00,9.569403357322088244e-01,8.314696123025452357e-01,6.343932841636454878e-01,3.826834323650898373e-01,9.801714032956077016e-02,-1.950903220161281926e-01,-4.713967368259976976e-01,-7.071067811865474617e-01,-8.819212643483549385e-01,-9.807852804032304306e-01,-9.951847266721969287e-01,-9.238795325112868495e-01,-7.730104533627371044e-01,-5.555702330196021776e-01,-2.902846772544624421e-01};
	static const WTYPE WI[48]={-0.000000000000000000e+00,-1.950903220161282481e-01,-3.826834323650897818e-01,-5.555702330196021776e-01,-7.071067811865474617e-01,-8.314696123025452357e-01,-9.238795325112867385e-01,-9.807852804032304306e-01,-1.000000000000000000e+00,-9.807852804032304306e-01,-9.238795325112867385e-01,-8.314696123025454577e-01,-7.071067811865475727e-01,-5.555702330196021776e-01,-3.826834323650898928e-01,-1.950903220161286089e-01,-0.000000000000000000e+00,-9.801714032956060363e-02,-1.950903220161282481e-01,-2.902846772544623311e-01,-3.826834323650897818e-01,-4.713967368259976420e-01,-5.555702330196021776e-01,-6.343932841636454878e-01,-7.071067811865474617e-01,-7.730104533627369934e-01,-8.314696123025452357e-01,-8.819212643483549385e-01,-9.238795325112867385e-01,-9.569403357322089354e-01,-9.807852804032304306e-01,-9.951847266721968177e-01,-0.000000000000000000e+00,-2.902846772544623311e-01,-5.555702330196021776e-01,-7.730104533627369934e-01,-9.238795325112867385e-01,-9.951847266721968177e-01,-9.807852804032304306e-01,-8.819212643483550496e-01,-7.071067811865475727e-01,-4.713967368259978641e-01,-1.950903220161286089e-01,9.801714032956058975e-02,3.826834323650896708e-01,6.343932841636452657e-01,8.314696123025452357e-01,9.569403357322088244e-01};
#pragma HLS ARRAY_RESHAPE variable=WR dim=1 complete
#pragma HLS ARRAY_RESHAPE variable=WI dim=1 complete

	MYDTYPE xr[2][RAM_PART_FCT];
	MYDTYPE xi[2][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=xr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=xr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=xi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=xi dim=2 complete

	MYDTYPE yr[2][RAM_PART_FCT];
	MYDTYPE yi[2][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=yr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=yr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=yi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=yi dim=2 complete

	WTYPE wr[3][RAM_PART_FCT];
	WTYPE wi[3][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=wr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=wr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=wi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=wi dim=2 complete

	int out_ram = 0;
	int out_addr = 0;

	// 循环16次, 每次16个butterfly
	for(int i = 0; i < FFTSIZE; i+=64) {
#pragma HLS PIPELINE ii=2

		// 读入相邻的64个数
		for(int j = 0; j < 2; j++) {
			for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL
				xr[j][n] = X_R[i+j*RAM_PART_FCT+n];
				xi[j][n] = X_I[i+j*RAM_PART_FCT+n];
			}
		}

		// 做16个蝶形计算
		for(int n = 0; n < 16; n++) {
#pragma HLS UNROLL
			r4_dif_butterfly(xr[0][n], xi[0][n], xr[0][n+16], xi[0][n+16], xr[1][n], xi[1][n], xr[1][n+16], xi[1][n+16],
					WR[n], WI[n], WR[n+16], WI[n+16], WR[n+32], WI[n+32],
					yr[0][n], yi[0][n], yr[0][n+16], yi[0][n+16], yr[1][n], yi[1][n], yr[1][n+16], yi[1][n+16]);
		}


		// 写出stream
		for( int j = 0; j < 2; j++) {
			ap_uint<1024> doutr_tmp;
			ap_uint<1024> douti_tmp;
			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				doutr_tmp(32*n+31, 32*n) = yr[j][n](31,0);
				douti_tmp(32*n+31, 32*n) = yi[j][n](31,0);

			}
			DOUTR[0].write(doutr_tmp);
			DOUTI[0].write(douti_tmp);
		}


	}

}

// butterfly stride 64
void fft_2(
		MYDTYPE X_R[FFTSIZE],
		MYDTYPE X_I[FFTSIZE],
		MYDTYPE DOUTR[FFTSIZE],
		MYDTYPE DOUTI[FFTSIZE]) {

	static const WTYPE WR[192]={1.000000000000000000e+00,9.987954562051724050e-01,9.951847266721969287e-01,9.891765099647810144e-01,9.807852804032304306e-01,9.700312531945439742e-01,9.569403357322088244e-01,9.415440651830208063e-01,9.238795325112867385e-01,9.039892931234433382e-01,8.819212643483550496e-01,8.577286100002721181e-01,8.314696123025452357e-01,8.032075314806449429e-01,7.730104533627369934e-01,7.409511253549591059e-01,7.071067811865475727e-01,6.715589548470183301e-01,6.343932841636454878e-01,5.956993044924334679e-01,5.555702330196022887e-01,5.141027441932216613e-01,4.713967368259978086e-01,4.275550934302821959e-01,3.826834323650898373e-01,3.368898533922200511e-01,2.902846772544623311e-01,2.429801799032639820e-01,1.950903220161283314e-01,1.467304744553617479e-01,9.801714032956077016e-02,4.906767432741812596e-02,6.123233995736766036e-17,-4.906767432741800800e-02,-9.801714032956064526e-02,-1.467304744553616369e-01,-1.950903220161281926e-01,-2.429801799032638709e-01,-2.902846772544621645e-01,-3.368898533922199401e-01,-3.826834323650897263e-01,-4.275550934302818629e-01,-4.713967368259976976e-01,-5.141027441932216613e-01,-5.555702330196019556e-01,-5.956993044924333569e-01,-6.343932841636453768e-01,-6.715589548470184411e-01,-7.071067811865474617e-01,-7.409511253549588838e-01,-7.730104533627369934e-01,-8.032075314806448318e-01,-8.314696123025453467e-01,-8.577286100002720071e-01,-8.819212643483549385e-01,-9.039892931234433382e-01,-9.238795325112867385e-01,-9.415440651830206953e-01,-9.569403357322088244e-01,-9.700312531945439742e-01,-9.807852804032304306e-01,-9.891765099647810144e-01,-9.951847266721968177e-01,-9.987954562051724050e-01,1.000000000000000000e+00,9.996988186962042500e-01,9.987954562051724050e-01,9.972904566786902070e-01,9.951847266721969287e-01,9.924795345987099671e-01,9.891765099647810144e-01,9.852776423889412216e-01,9.807852804032304306e-01,9.757021300385285700e-01,9.700312531945439742e-01,9.637760657954398402e-01,9.569403357322088244e-01,9.495281805930366748e-01,9.415440651830208063e-01,9.329927988347389567e-01,9.238795325112867385e-01,9.142097557035306910e-01,9.039892931234433382e-01,8.932243011955153245e-01,8.819212643483550496e-01,8.700869911087114605e-01,8.577286100002721181e-01,8.448535652497071169e-01,8.314696123025452357e-01,8.175848131515837114e-01,8.032075314806449429e-01,7.883464276266063386e-01,7.730104533627369934e-01,7.572088465064845675e-01,7.409511253549591059e-01,7.242470829514670028e-01,7.071067811865475727e-01,6.895405447370669405e-01,6.715589548470183301e-01,6.531728429537767555e-01,6.343932841636454878e-01,6.152315905806268193e-01,5.956993044924334679e-01,5.758081914178453387e-01,5.555702330196022887e-01,5.349976198870972643e-01,5.141027441932216613e-01,4.928981922297840934e-01,4.713967368259978086e-01,4.496113296546065952e-01,4.275550934302821959e-01,4.052413140049898610e-01,3.826834323650898373e-01,3.598950365349882774e-01,3.368898533922200511e-01,3.136817403988915731e-01,2.902846772544623311e-01,2.667127574748984209e-01,2.429801799032639820e-01,2.191012401568697698e-01,1.950903220161283314e-01,1.709618887603013559e-01,1.467304744553617479e-01,1.224106751992162789e-01,9.801714032956077016e-02,7.356456359966745406e-02,4.906767432741812596e-02,2.454122852291226384e-02,1.000000000000000000e+00,9.972904566786902070e-01,9.891765099647810144e-01,9.757021300385285700e-01,9.569403357322088244e-01,9.329927988347389567e-01,9.039892931234433382e-01,8.700869911087114605e-01,8.314696123025452357e-01,7.883464276266063386e-01,7.409511253549591059e-01,6.895405447370669405e-01,6.343932841636454878e-01,5.758081914178453387e-01,5.141027441932216613e-01,4.496113296546065952e-01,3.826834323650898373e-01,3.136817403988915731e-01,2.429801799032639820e-01,1.709618887603013559e-01,9.801714032956077016e-02,2.454122852291226384e-02,-4.906767432741800800e-02,-1.224106751992161540e-01,-1.950903220161281926e-01,-2.667127574748983099e-01,-3.368898533922199401e-01,-4.052413140049897500e-01,-4.713967368259976976e-01,-5.349976198870970423e-01,-5.956993044924333569e-01,-6.531728429537765335e-01,-7.071067811865474617e-01,-7.572088465064845675e-01,-8.032075314806448318e-01,-8.448535652497071169e-01,-8.819212643483549385e-01,-9.142097557035306910e-01,-9.415440651830206953e-01,-9.637760657954398402e-01,-9.807852804032304306e-01,-9.924795345987099671e-01,-9.987954562051724050e-01,-9.996988186962042500e-01,-9.951847266721969287e-01,-9.852776423889413326e-01,-9.700312531945439742e-01,-9.495281805930367858e-01,-9.238795325112868495e-01,-8.932243011955153245e-01,-8.577286100002721181e-01,-8.175848131515837114e-01,-7.730104533627371044e-01,-7.242470829514670028e-01,-6.715589548470186632e-01,-6.152315905806272633e-01,-5.555702330196021776e-01,-4.928981922297842044e-01,-4.275550934302824735e-01,-3.598950365349879443e-01,-2.902846772544624421e-01,-2.191012401568701029e-01,-1.467304744553623030e-01,-7.356456359966735692e-02};
	static const WTYPE WI[192]={-0.000000000000000000e+00,-4.906767432741801493e-02,-9.801714032956060363e-02,-1.467304744553617479e-01,-1.950903220161282481e-01,-2.429801799032638709e-01,-2.902846772544623311e-01,-3.368898533922200511e-01,-3.826834323650897818e-01,-4.275550934302820849e-01,-4.713967368259976420e-01,-5.141027441932216613e-01,-5.555702330196021776e-01,-5.956993044924333569e-01,-6.343932841636454878e-01,-6.715589548470183301e-01,-7.071067811865474617e-01,-7.409511253549591059e-01,-7.730104533627369934e-01,-8.032075314806448318e-01,-8.314696123025452357e-01,-8.577286100002721181e-01,-8.819212643483549385e-01,-9.039892931234433382e-01,-9.238795325112867385e-01,-9.415440651830208063e-01,-9.569403357322089354e-01,-9.700312531945439742e-01,-9.807852804032304306e-01,-9.891765099647810144e-01,-9.951847266721968177e-01,-9.987954562051724050e-01,-1.000000000000000000e+00,-9.987954562051724050e-01,-9.951847266721969287e-01,-9.891765099647810144e-01,-9.807852804032304306e-01,-9.700312531945439742e-01,-9.569403357322089354e-01,-9.415440651830208063e-01,-9.238795325112867385e-01,-9.039892931234434492e-01,-8.819212643483550496e-01,-8.577286100002721181e-01,-8.314696123025454577e-01,-8.032075314806449429e-01,-7.730104533627371044e-01,-7.409511253549589949e-01,-7.071067811865475727e-01,-6.715589548470185521e-01,-6.343932841636454878e-01,-5.956993044924334679e-01,-5.555702330196021776e-01,-5.141027441932217723e-01,-4.713967368259978641e-01,-4.275550934302820294e-01,-3.826834323650898928e-01,-3.368898533922203287e-01,-2.902846772544623866e-01,-2.429801799032640652e-01,-1.950903220161286089e-01,-1.467304744553618034e-01,-9.801714032956082567e-02,-4.906767432741796636e-02,-0.000000000000000000e+00,-2.454122852291228812e-02,-4.906767432741801493e-02,-7.356456359966742631e-02,-9.801714032956060363e-02,-1.224106751992161957e-01,-1.467304744553617479e-01,-1.709618887603012172e-01,-1.950903220161282481e-01,-2.191012401568697976e-01,-2.429801799032638709e-01,-2.667127574748983654e-01,-2.902846772544623311e-01,-3.136817403988915176e-01,-3.368898533922200511e-01,-3.598950365349881109e-01,-3.826834323650897818e-01,-4.052413140049898610e-01,-4.275550934302820849e-01,-4.496113296546065397e-01,-4.713967368259976420e-01,-4.928981922297840379e-01,-5.141027441932216613e-01,-5.349976198870971533e-01,-5.555702330196021776e-01,-5.758081914178453387e-01,-5.956993044924333569e-01,-6.152315905806268193e-01,-6.343932841636454878e-01,-6.531728429537767555e-01,-6.715589548470183301e-01,-6.895405447370668295e-01,-7.071067811865474617e-01,-7.242470829514668917e-01,-7.409511253549591059e-01,-7.572088465064844565e-01,-7.730104533627369934e-01,-7.883464276266062276e-01,-8.032075314806448318e-01,-8.175848131515837114e-01,-8.314696123025452357e-01,-8.448535652497070059e-01,-8.577286100002721181e-01,-8.700869911087113495e-01,-8.819212643483549385e-01,-8.932243011955153245e-01,-9.039892931234433382e-01,-9.142097557035306910e-01,-9.238795325112867385e-01,-9.329927988347388457e-01,-9.415440651830208063e-01,-9.495281805930366748e-01,-9.569403357322089354e-01,-9.637760657954398402e-01,-9.700312531945439742e-01,-9.757021300385285700e-01,-9.807852804032304306e-01,-9.852776423889412216e-01,-9.891765099647810144e-01,-9.924795345987099671e-01,-9.951847266721968177e-01,-9.972904566786902070e-01,-9.987954562051724050e-01,-9.996988186962042500e-01,-0.000000000000000000e+00,-7.356456359966742631e-02,-1.467304744553617479e-01,-2.191012401568697976e-01,-2.902846772544623311e-01,-3.598950365349881109e-01,-4.275550934302820849e-01,-4.928981922297840379e-01,-5.555702330196021776e-01,-6.152315905806268193e-01,-6.715589548470183301e-01,-7.242470829514668917e-01,-7.730104533627369934e-01,-8.175848131515837114e-01,-8.577286100002721181e-01,-8.932243011955153245e-01,-9.238795325112867385e-01,-9.495281805930366748e-01,-9.700312531945439742e-01,-9.852776423889412216e-01,-9.951847266721968177e-01,-9.996988186962042500e-01,-9.987954562051724050e-01,-9.924795345987099671e-01,-9.807852804032304306e-01,-9.637760657954398402e-01,-9.415440651830208063e-01,-9.142097557035306910e-01,-8.819212643483550496e-01,-8.448535652497072279e-01,-8.032075314806449429e-01,-7.572088465064846785e-01,-7.071067811865475727e-01,-6.531728429537766445e-01,-5.956993044924334679e-01,-5.349976198870971533e-01,-4.713967368259978641e-01,-4.052413140049899165e-01,-3.368898533922203287e-01,-2.667127574748984764e-01,-1.950903220161286089e-01,-1.224106751992163483e-01,-4.906767432741796636e-02,2.454122852291207996e-02,9.801714032956058975e-02,1.709618887603009674e-01,2.429801799032638154e-01,3.136817403988911845e-01,3.826834323650896708e-01,4.496113296546066507e-01,5.141027441932215503e-01,5.758081914178453387e-01,6.343932841636452657e-01,6.895405447370668295e-01,7.409511253549588838e-01,7.883464276266058945e-01,8.314696123025452357e-01,8.700869911087113495e-01,9.039892931234431162e-01,9.329927988347389567e-01,9.569403357322088244e-01,9.757021300385284590e-01,9.891765099647809034e-01,9.972904566786902070e-01};
#pragma HLS ARRAY_RESHAPE variable=WR dim=1 factor=RAM_PART_FCT cyclic
#pragma HLS ARRAY_RESHAPE variable=WI dim=1 factor=RAM_PART_FCT cyclic

	MYDTYPE xr[4][RAM_PART_FCT];
	MYDTYPE xi[4][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=xr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=xr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=xi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=xi dim=2 complete

	MYDTYPE yr[4][RAM_PART_FCT];
	MYDTYPE yi[4][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=yr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=yr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=yi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=yi dim=2 complete

	WTYPE wr[3][RAM_PART_FCT];
	WTYPE wi[3][RAM_PART_FCT];
	#pragma HLS ARRAY_PARTITION variable=wr dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=wr dim=2 complete
	#pragma HLS ARRAY_PARTITION variable=wi dim=1 complete
	#pragma HLS ARRAY_PARTITION variable=wi dim=2 complete


int i = 0, k=0;
// 循环8次, 每次32个butterfly
for(int cnt = 0; cnt < 8; cnt++) {
#pragma HLS PIPELINE ii=4

		// 读入4段数据, butterfly stride 64
		for(int j = 0; j < 4; j++) {
			for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL
				xr[j][n] = X_R[k*256+j*64+i*RAM_PART_FCT+n];
				xi[j][n] = X_I[k*256+j*64+i*RAM_PART_FCT+n];
			}
		}

		// 读入旋转因子
		for(int j = 0; j < 3; j++) {
			for(int n = 0; n < RAM_PART_FCT; n++){
	#pragma HLS UNROLL
				wr[j][n] = WR[j*64+i*RAM_PART_FCT+n];
				wi[j][n] = WI[j*64+i*RAM_PART_FCT+n];
			}
		}

		r4_dif_butterfly(xr, xi, wr, wi, yr, yi);

		//
		for( int j = 0; j < 4; j++) {
			for(int n = 0; n < RAM_PART_FCT; n++) {
	#pragma HLS UNROLL
				DOUTR[k*256+i*RAM_PART_FCT+j*64+n] = yr[j][n];
				DOUTI[k*256+i*RAM_PART_FCT+j*64+n] = yi[j][n];
			}
		}

		i+=1;
		if(i == 2) {
			i=0;
			k+=1;
		}
}

}



// butterfly stride 256
void fft_1(DTYPE X_R[FFTSIZE], DTYPE X_I[FFTSIZE],
		MYDTYPE DOUTR[FFTSIZE],
		MYDTYPE DOUTI[FFTSIZE]) {
	static const WTYPE WR[768]={1.000000000000000000e+00,9.999247018391445030e-01,9.996988186962042500e-01,9.993223845883495438e-01,9.987954562051724050e-01,9.981181129001491792e-01,9.972904566786902070e-01,9.963126121827780013e-01,9.951847266721969287e-01,9.939069700023560605e-01,9.924795345987099671e-01,9.909026354277800097e-01,9.891765099647810144e-01,9.873014181578584347e-01,9.852776423889412216e-01,9.831054874312162850e-01,9.807852804032304306e-01,9.783173707196276547e-01,9.757021300385285700e-01,9.729399522055601768e-01,9.700312531945439742e-01,9.669764710448520706e-01,9.637760657954398402e-01,9.604305194155657865e-01,9.569403357322088244e-01,9.533060403541938621e-01,9.495281805930366748e-01,9.456073253805212797e-01,9.415440651830208063e-01,9.373390119125749598e-01,9.329927988347389567e-01,9.285060804732155892e-01,9.238795325112867385e-01,9.191138516900577704e-01,9.142097557035306910e-01,9.091679830905223803e-01,9.039892931234433382e-01,8.986744656939538167e-01,8.932243011955153245e-01,8.876396204028539350e-01,8.819212643483550496e-01,8.760700941954066012e-01,8.700869911087114605e-01,8.639728561215868075e-01,8.577286100002721181e-01,8.513551931052651955e-01,8.448535652497071169e-01,8.382247055548380787e-01,8.314696123025452357e-01,8.245893027850252910e-01,8.175848131515837114e-01,8.104571982525947682e-01,8.032075314806449429e-01,7.958369046088835663e-01,7.883464276266063386e-01,7.807372285720944882e-01,7.730104533627369934e-01,7.651672656224589586e-01,7.572088465064845675e-01,7.491363945234593702e-01,7.409511253549591059e-01,7.326542716724128157e-01,7.242470829514670028e-01,7.157308252838185947e-01,7.071067811865475727e-01,6.983762494089729156e-01,6.895405447370669405e-01,6.806009977954531331e-01,6.715589548470183301e-01,6.624157775901717837e-01,6.531728429537767555e-01,6.438315428897914972e-01,6.343932841636454878e-01,6.248594881423864544e-01,6.152315905806268193e-01,6.055110414043255451e-01,5.956993044924334679e-01,5.857978574564388641e-01,5.758081914178453387e-01,5.657318107836132315e-01,5.555702330196022887e-01,5.453249884220464638e-01,5.349976198870972643e-01,5.245896826784688383e-01,5.141027441932216613e-01,5.035383837257175754e-01,4.928981922297840934e-01,4.821837720791228299e-01,4.713967368259978086e-01,4.605387109582400051e-01,4.496113296546065952e-01,4.386162385385277140e-01,4.275550934302821959e-01,4.164295600976373191e-01,4.052413140049898610e-01,3.939920400610480988e-01,3.826834323650898373e-01,3.713171939518375986e-01,3.598950365349882774e-01,3.484186802494345092e-01,3.368898533922200511e-01,3.253102921622629817e-01,3.136817403988915731e-01,3.020059493192281952e-01,2.902846772544623311e-01,2.785196893850530597e-01,2.667127574748984209e-01,2.548656596045146272e-01,2.429801799032639820e-01,2.310581082806712760e-01,2.191012401568697698e-01,2.071113761922185603e-01,1.950903220161283314e-01,1.830398879551410618e-01,1.709618887603013559e-01,1.588581433338613902e-01,1.467304744553617479e-01,1.345807085071262232e-01,1.224106751992162789e-01,1.102222072938831843e-01,9.801714032956077016e-02,8.579731234443987997e-02,7.356456359966745406e-02,6.132073630220864768e-02,4.906767432741812596e-02,3.680722294135899131e-02,2.454122852291226384e-02,1.227153828571994447e-02,6.123233995736766036e-17,-1.227153828571982304e-02,-2.454122852291214241e-02,-3.680722294135886641e-02,-4.906767432741800800e-02,-6.132073630220852972e-02,-7.356456359966732916e-02,-8.579731234443975507e-02,-9.801714032956064526e-02,-1.102222072938830594e-01,-1.224106751992161540e-01,-1.345807085071261122e-01,-1.467304744553616369e-01,-1.588581433338612792e-01,-1.709618887603012449e-01,-1.830398879551409230e-01,-1.950903220161281926e-01,-2.071113761922184493e-01,-2.191012401568696588e-01,-2.310581082806711373e-01,-2.429801799032638709e-01,-2.548656596045145162e-01,-2.667127574748983099e-01,-2.785196893850529487e-01,-2.902846772544621645e-01,-3.020059493192280842e-01,-3.136817403988914066e-01,-3.253102921622628707e-01,-3.368898533922199401e-01,-3.484186802494343982e-01,-3.598950365349881664e-01,-3.713171939518374876e-01,-3.826834323650897263e-01,-3.939920400610479878e-01,-4.052413140049897500e-01,-4.164295600976369860e-01,-4.275550934302818629e-01,-4.386162385385273810e-01,-4.496113296546067062e-01,-4.605387109582400607e-01,-4.713967368259976976e-01,-4.821837720791227189e-01,-4.928981922297839824e-01,-5.035383837257174644e-01,-5.141027441932216613e-01,-5.245896826784687272e-01,-5.349976198870970423e-01,-5.453249884220462418e-01,-5.555702330196019556e-01,-5.657318107836132315e-01,-5.758081914178453387e-01,-5.857978574564388641e-01,-5.956993044924333569e-01,-6.055110414043254341e-01,-6.152315905806267082e-01,-6.248594881423862324e-01,-6.343932841636453768e-01,-6.438315428897912751e-01,-6.531728429537765335e-01,-6.624157775901718948e-01,-6.715589548470184411e-01,-6.806009977954530221e-01,-6.895405447370669405e-01,-6.983762494089728046e-01,-7.071067811865474617e-01,-7.157308252838185947e-01,-7.242470829514667807e-01,-7.326542716724127047e-01,-7.409511253549588838e-01,-7.491363945234591482e-01,-7.572088465064845675e-01,-7.651672656224589586e-01,-7.730104533627369934e-01,-7.807372285720944882e-01,-7.883464276266062276e-01,-7.958369046088834553e-01,-8.032075314806448318e-01,-8.104571982525946572e-01,-8.175848131515836004e-01,-8.245893027850250689e-01,-8.314696123025453467e-01,-8.382247055548380787e-01,-8.448535652497071169e-01,-8.513551931052651955e-01,-8.577286100002720071e-01,-8.639728561215866964e-01,-8.700869911087113495e-01,-8.760700941954064902e-01,-8.819212643483549385e-01,-8.876396204028538239e-01,-8.932243011955152134e-01,-8.986744656939539277e-01,-9.039892931234433382e-01,-9.091679830905223803e-01,-9.142097557035306910e-01,-9.191138516900577704e-01,-9.238795325112867385e-01,-9.285060804732154782e-01,-9.329927988347388457e-01,-9.373390119125748488e-01,-9.415440651830206953e-01,-9.456073253805211687e-01,-9.495281805930366748e-01,-9.533060403541938621e-01,-9.569403357322088244e-01,-9.604305194155657865e-01,-9.637760657954398402e-01,-9.669764710448520706e-01,-9.700312531945439742e-01,-9.729399522055600658e-01,-9.757021300385284590e-01,-9.783173707196275437e-01,-9.807852804032304306e-01,-9.831054874312162850e-01,-9.852776423889412216e-01,-9.873014181578584347e-01,-9.891765099647810144e-01,-9.909026354277800097e-01,-9.924795345987099671e-01,-9.939069700023560605e-01,-9.951847266721968177e-01,-9.963126121827780013e-01,-9.972904566786902070e-01,-9.981181129001491792e-01,-9.987954562051724050e-01,-9.993223845883495438e-01,-9.996988186962042500e-01,-9.999247018391445030e-01,1.000000000000000000e+00,9.999811752826011091e-01,9.999247018391445030e-01,9.998305817958234032e-01,9.996988186962042500e-01,9.995294175010931426e-01,9.993223845883495438e-01,9.990777277526453615e-01,9.987954562051724050e-01,9.984755805732947742e-01,9.981181129001491792e-01,9.977230666441916362e-01,9.972904566786902070e-01,9.968202992911656679e-01,9.963126121827780013e-01,9.957674144676598171e-01,9.951847266721969287e-01,9.945645707342554154e-01,9.939069700023560605e-01,9.932119492347945000e-01,9.924795345987099671e-01,9.917097536690995252e-01,9.909026354277800097e-01,9.900582102622971226e-01,9.891765099647810144e-01,9.882575677307494644e-01,9.873014181578584347e-01,9.863080972445986694e-01,9.852776423889412216e-01,9.842100923869290252e-01,9.831054874312162850e-01,9.819638691095552430e-01,9.807852804032304306e-01,9.795697656854405189e-01,9.783173707196276547e-01,9.770281426577543948e-01,9.757021300385285700e-01,9.743393827855758582e-01,9.729399522055601768e-01,9.715038909862517835e-01,9.700312531945439742e-01,9.685220942744173778e-01,9.669764710448520706e-01,9.653944416976893983e-01,9.637760657954398402e-01,9.621214042690415802e-01,9.604305194155657865e-01,9.587034748958715991e-01,9.569403357322088244e-01,9.551411683057707824e-01,9.533060403541938621e-01,9.514350209690083382e-01,9.495281805930366748e-01,9.475855910177410912e-01,9.456073253805212797e-01,9.435934581619603856e-01,9.415440651830208063e-01,9.394592236021899190e-01,9.373390119125749598e-01,9.351835099389476103e-01,9.329927988347389567e-01,9.307669610789837122e-01,9.285060804732155892e-01,9.262102421383113793e-01,9.238795325112867385e-01,9.215140393420420128e-01,9.191138516900577704e-01,9.166790599210427049e-01,9.142097557035306910e-01,9.117060320054298783e-01,9.091679830905223803e-01,9.065957045149153348e-01,9.039892931234433382e-01,9.013488470460220281e-01,8.986744656939538167e-01,8.959662497561852179e-01,8.932243011955153245e-01,8.904487232447578782e-01,8.876396204028539350e-01,8.847970984309377895e-01,8.819212643483550496e-01,8.790122264286335252e-01,8.760700941954066012e-01,8.730949784182900908e-01,8.700869911087114605e-01,8.670462455156926485e-01,8.639728561215868075e-01,8.608669386377673094e-01,8.577286100002721181e-01,8.545579883654005338e-01,8.513551931052651955e-01,8.481203448032972325e-01,8.448535652497071169e-01,8.415549774368984437e-01,8.382247055548380787e-01,8.348628749863800103e-01,8.314696123025452357e-01,8.280450452577557963e-01,8.245893027850252910e-01,8.211025149911046483e-01,8.175848131515837114e-01,8.140363297059484138e-01,8.104571982525947682e-01,8.068475535437993340e-01,8.032075314806449429e-01,7.995372691079050131e-01,7.958369046088835663e-01,7.921065773002123889e-01,7.883464276266063386e-01,7.845565971555752416e-01,7.807372285720944882e-01,7.768884656732324423e-01,7.730104533627369934e-01,7.691033376455796988e-01,7.651672656224589586e-01,7.612023854842617787e-01,7.572088465064845675e-01,7.531867990436125204e-01,7.491363945234593702e-01,7.450577854414660584e-01,7.409511253549591059e-01,7.368165688773699040e-01,7.326542716724128157e-01,7.284643904482251964e-01,7.242470829514670028e-01,7.200025079613816548e-01,7.157308252838185947e-01,7.114321957452164336e-01,7.071067811865475727e-01,7.027547444572252999e-01,6.983762494089729156e-01,6.939714608896540016e-01,6.895405447370669405e-01,6.850836677727003554e-01,6.806009977954531331e-01,6.760927035753160341e-01,6.715589548470183301e-01,6.669999223036374714e-01,6.624157775901717837e-01,6.578066932970786374e-01,6.531728429537767555e-01,6.485144010221125521e-01,6.438315428897914972e-01,6.391244448637757314e-01,6.343932841636454878e-01,6.296382389149270953e-01,6.248594881423864544e-01,6.200572117632892066e-01,6.152315905806268193e-01,6.103828062763094753e-01,6.055110414043255451e-01,6.006164793838689731e-01,5.956993044924334679e-01,5.907597018588742754e-01,5.857978574564388641e-01,5.808139580957645265e-01,5.758081914178453387e-01,5.707807458869673667e-01,5.657318107836132315e-01,5.606615761973360312e-01,5.555702330196022887e-01,5.504579729366048113e-01,5.453249884220464638e-01,5.401714727298929652e-01,5.349976198870972643e-01,5.298036246862948273e-01,5.245896826784688383e-01,5.193559901655895317e-01,5.141027441932216613e-01,5.088301425431069891e-01,5.035383837257175754e-01,4.982276669727818685e-01,4.928981922297840934e-01,4.875501601484360514e-01,4.821837720791228299e-01,4.767992300633222547e-01,4.713967368259978086e-01,4.659764957679661257e-01,4.605387109582400051e-01,4.550835871263438359e-01,4.496113296546065952e-01,4.441221445704292559e-01,4.386162385385277140e-01,4.330938188531520128e-01,4.275550934302821959e-01,4.220002707997997926e-01,4.164295600976373191e-01,4.108431710579039109e-01,4.052413140049898610e-01,3.996241998456467881e-01,3.939920400610480988e-01,3.883450466988263017e-01,3.826834323650898373e-01,3.770074102164183150e-01,3.713171939518375986e-01,3.656129978047739648e-01,3.598950365349882774e-01,3.541635254204905103e-01,3.484186802494345092e-01,3.426607173119943783e-01,3.368898533922200511e-01,3.311063057598764292e-01,3.253102921622629817e-01,3.195020308160157474e-01,3.136817403988915731e-01,3.078496400415349776e-01,3.020059493192281952e-01,2.961508882436239554e-01,2.902846772544623311e-01,2.844075372112718214e-01,2.785196893850530597e-01,2.726213554499489766e-01,2.667127574748984209e-01,2.607941179152755695e-01,2.548656596045146272e-01,2.489276057457202596e-01,2.429801799032639820e-01,2.370236059943673368e-01,2.310581082806712760e-01,2.250839113597927765e-01,2.191012401568697698e-01,2.131103199160913619e-01,2.071113761922185603e-01,2.011046348420919561e-01,1.950903220161283314e-01,1.890686641498062759e-01,1.830398879551410618e-01,1.770042204121488605e-01,1.709618887603013559e-01,1.649131204899700887e-01,1.588581433338613902e-01,1.527971852584434076e-01,1.467304744553617479e-01,1.406582393328492386e-01,1.345807085071262232e-01,1.284981107937932243e-01,1.224106751992162789e-01,1.163186309119048772e-01,1.102222072938831843e-01,1.041216338720547252e-01,9.801714032956077016e-02,9.190895649713269611e-02,8.579731234443987997e-02,7.968243797143012563e-02,7.356456359966745406e-02,6.744391956366410645e-02,6.132073630220864768e-02,5.519524434969003135e-02,4.906767432741812596e-02,4.293825693494095902e-02,3.680722294135899131e-02,3.067480317663658085e-02,2.454122852291226384e-02,1.840672990580482019e-02,1.227153828571994447e-02,6.135884649154515168e-03,1.000000000000000000e+00,9.998305817958234032e-01,9.993223845883495438e-01,9.984755805732947742e-01,9.972904566786902070e-01,9.957674144676598171e-01,9.939069700023560605e-01,9.917097536690995252e-01,9.891765099647810144e-01,9.863080972445986694e-01,9.831054874312162850e-01,9.795697656854405189e-01,9.757021300385285700e-01,9.715038909862517835e-01,9.669764710448520706e-01,9.621214042690415802e-01,9.569403357322088244e-01,9.514350209690083382e-01,9.456073253805212797e-01,9.394592236021899190e-01,9.329927988347389567e-01,9.262102421383113793e-01,9.191138516900577704e-01,9.117060320054298783e-01,9.039892931234433382e-01,8.959662497561852179e-01,8.876396204028539350e-01,8.790122264286335252e-01,8.700869911087114605e-01,8.608669386377673094e-01,8.513551931052651955e-01,8.415549774368984437e-01,8.314696123025452357e-01,8.211025149911046483e-01,8.104571982525947682e-01,7.995372691079050131e-01,7.883464276266063386e-01,7.768884656732324423e-01,7.651672656224589586e-01,7.531867990436125204e-01,7.409511253549591059e-01,7.284643904482251964e-01,7.157308252838185947e-01,7.027547444572252999e-01,6.895405447370669405e-01,6.760927035753160341e-01,6.624157775901717837e-01,6.485144010221125521e-01,6.343932841636454878e-01,6.200572117632892066e-01,6.055110414043255451e-01,5.907597018588742754e-01,5.758081914178453387e-01,5.606615761973360312e-01,5.453249884220464638e-01,5.298036246862948273e-01,5.141027441932216613e-01,4.982276669727818685e-01,4.821837720791228299e-01,4.659764957679661257e-01,4.496113296546065952e-01,4.330938188531520128e-01,4.164295600976373191e-01,3.996241998456467881e-01,3.826834323650898373e-01,3.656129978047739648e-01,3.484186802494345092e-01,3.311063057598764292e-01,3.136817403988915731e-01,2.961508882436239554e-01,2.785196893850530597e-01,2.607941179152755695e-01,2.429801799032639820e-01,2.250839113597927765e-01,2.071113761922185603e-01,1.890686641498062759e-01,1.709618887603013559e-01,1.527971852584434076e-01,1.345807085071262232e-01,1.163186309119048772e-01,9.801714032956077016e-02,7.968243797143012563e-02,6.132073630220864768e-02,4.293825693494095902e-02,2.454122852291226384e-02,6.135884649154515168e-03,-1.227153828571982304e-02,-3.067480317663645942e-02,-4.906767432741800800e-02,-6.744391956366398155e-02,-8.579731234443975507e-02,-1.041216338720546003e-01,-1.224106751992161540e-01,-1.406582393328491276e-01,-1.588581433338612792e-01,-1.770042204121487495e-01,-1.950903220161281926e-01,-2.131103199160912509e-01,-2.310581082806711373e-01,-2.489276057457201208e-01,-2.667127574748983099e-01,-2.844075372112717104e-01,-3.020059493192280842e-01,-3.195020308160156364e-01,-3.368898533922199401e-01,-3.541635254204903993e-01,-3.713171939518374876e-01,-3.883450466988261907e-01,-4.052413140049897500e-01,-4.220002707997996816e-01,-4.386162385385273810e-01,-4.550835871263437249e-01,-4.713967368259976976e-01,-4.875501601484357184e-01,-5.035383837257174644e-01,-5.193559901655896427e-01,-5.349976198870970423e-01,-5.504579729366047003e-01,-5.657318107836132315e-01,-5.808139580957644155e-01,-5.956993044924333569e-01,-6.103828062763095863e-01,-6.248594881423862324e-01,-6.391244448637757314e-01,-6.531728429537765335e-01,-6.669999223036373603e-01,-6.806009977954530221e-01,-6.939714608896537795e-01,-7.071067811865474617e-01,-7.200025079613816548e-01,-7.326542716724127047e-01,-7.450577854414659473e-01,-7.572088465064845675e-01,-7.691033376455794768e-01,-7.807372285720944882e-01,-7.921065773002121668e-01,-8.032075314806448318e-01,-8.140363297059484138e-01,-8.245893027850250689e-01,-8.348628749863800103e-01,-8.448535652497071169e-01,-8.545579883654004227e-01,-8.639728561215866964e-01,-8.730949784182900908e-01,-8.819212643483549385e-01,-8.904487232447578782e-01,-8.986744656939539277e-01,-9.065957045149153348e-01,-9.142097557035306910e-01,-9.215140393420417908e-01,-9.285060804732154782e-01,-9.351835099389476103e-01,-9.415440651830206953e-01,-9.475855910177410912e-01,-9.533060403541938621e-01,-9.587034748958714880e-01,-9.637760657954398402e-01,-9.685220942744173778e-01,-9.729399522055600658e-01,-9.770281426577543948e-01,-9.807852804032304306e-01,-9.842100923869290252e-01,-9.873014181578584347e-01,-9.900582102622970115e-01,-9.924795345987099671e-01,-9.945645707342554154e-01,-9.963126121827780013e-01,-9.977230666441916362e-01,-9.987954562051724050e-01,-9.995294175010931426e-01,-9.999247018391445030e-01,-9.999811752826011091e-01,-9.996988186962042500e-01,-9.990777277526453615e-01,-9.981181129001491792e-01,-9.968202992911657789e-01,-9.951847266721969287e-01,-9.932119492347946110e-01,-9.909026354277800097e-01,-9.882575677307494644e-01,-9.852776423889413326e-01,-9.819638691095552430e-01,-9.783173707196276547e-01,-9.743393827855758582e-01,-9.700312531945439742e-01,-9.653944416976893983e-01,-9.604305194155658976e-01,-9.551411683057707824e-01,-9.495281805930367858e-01,-9.435934581619603856e-01,-9.373390119125749598e-01,-9.307669610789838233e-01,-9.238795325112868495e-01,-9.166790599210427049e-01,-9.091679830905224913e-01,-9.013488470460220281e-01,-8.932243011955153245e-01,-8.847970984309379006e-01,-8.760700941954066012e-01,-8.670462455156928705e-01,-8.577286100002721181e-01,-8.481203448032972325e-01,-8.382247055548381898e-01,-8.280450452577557963e-01,-8.175848131515837114e-01,-8.068475535437994450e-01,-7.958369046088835663e-01,-7.845565971555752416e-01,-7.730104533627371044e-01,-7.612023854842618897e-01,-7.491363945234592592e-01,-7.368165688773700150e-01,-7.242470829514670028e-01,-7.114321957452166556e-01,-6.983762494089730266e-01,-6.850836677727003554e-01,-6.715589548470186632e-01,-6.578066932970787484e-01,-6.438315428897914972e-01,-6.296382389149268732e-01,-6.152315905806272633e-01,-6.006164793838693061e-01,-5.857978574564390861e-01,-5.707807458869673667e-01,-5.555702330196021776e-01,-5.401714727298927432e-01,-5.245896826784693934e-01,-5.088301425431073222e-01,-4.928981922297842044e-01,-4.767992300633221436e-01,-4.605387109582398941e-01,-4.441221445704297555e-01,-4.275550934302824735e-01,-4.108431710579041884e-01,-3.939920400610482099e-01,-3.770074102164182039e-01,-3.598950365349879443e-01,-3.426607173119948779e-01,-3.253102921622633148e-01,-3.078496400415350887e-01,-2.902846772544624421e-01,-2.726213554499488656e-01,-2.548656596045143496e-01,-2.370236059943676699e-01,-2.191012401568701029e-01,-2.011046348420920671e-01,-1.830398879551409508e-01,-1.649131204899697556e-01,-1.467304744553623030e-01,-1.284981107937935851e-01,-1.102222072938833092e-01,-9.190895649713282101e-02,-7.356456359966735692e-02,-5.519524434968971216e-02,-3.680722294135933131e-02,-1.840672990580516366e-02};
	static const WTYPE WI[768]={-0.000000000000000000e+00,-1.227153828571992539e-02,-2.454122852291228812e-02,-3.680722294135883171e-02,-4.906767432741801493e-02,-6.132073630220857829e-02,-7.356456359966742631e-02,-8.579731234443989385e-02,-9.801714032956060363e-02,-1.102222072938830594e-01,-1.224106751992161957e-01,-1.345807085071261677e-01,-1.467304744553617479e-01,-1.588581433338614457e-01,-1.709618887603012172e-01,-1.830398879551409508e-01,-1.950903220161282481e-01,-2.071113761922185603e-01,-2.191012401568697976e-01,-2.310581082806711095e-01,-2.429801799032638709e-01,-2.548656596045145717e-01,-2.667127574748983654e-01,-2.785196893850530597e-01,-2.902846772544623311e-01,-3.020059493192280842e-01,-3.136817403988915176e-01,-3.253102921622629262e-01,-3.368898533922200511e-01,-3.484186802494345647e-01,-3.598950365349881109e-01,-3.713171939518375431e-01,-3.826834323650897818e-01,-3.939920400610480988e-01,-4.052413140049898610e-01,-4.164295600976371525e-01,-4.275550934302820849e-01,-4.386162385385276585e-01,-4.496113296546065397e-01,-4.605387109582400051e-01,-4.713967368259976420e-01,-4.821837720791227189e-01,-4.928981922297840379e-01,-5.035383837257175754e-01,-5.141027441932216613e-01,-5.245896826784689493e-01,-5.349976198870971533e-01,-5.453249884220464638e-01,-5.555702330196021776e-01,-5.657318107836131205e-01,-5.758081914178453387e-01,-5.857978574564388641e-01,-5.956993044924333569e-01,-6.055110414043255451e-01,-6.152315905806268193e-01,-6.248594881423863434e-01,-6.343932841636454878e-01,-6.438315428897913861e-01,-6.531728429537767555e-01,-6.624157775901717837e-01,-6.715589548470183301e-01,-6.806009977954530221e-01,-6.895405447370668295e-01,-6.983762494089729156e-01,-7.071067811865474617e-01,-7.157308252838185947e-01,-7.242470829514668917e-01,-7.326542716724128157e-01,-7.409511253549591059e-01,-7.491363945234592592e-01,-7.572088465064844565e-01,-7.651672656224589586e-01,-7.730104533627369934e-01,-7.807372285720943772e-01,-7.883464276266062276e-01,-7.958369046088834553e-01,-8.032075314806448318e-01,-8.104571982525947682e-01,-8.175848131515837114e-01,-8.245893027850252910e-01,-8.314696123025452357e-01,-8.382247055548379677e-01,-8.448535652497070059e-01,-8.513551931052651955e-01,-8.577286100002721181e-01,-8.639728561215866964e-01,-8.700869911087113495e-01,-8.760700941954066012e-01,-8.819212643483549385e-01,-8.876396204028539350e-01,-8.932243011955153245e-01,-8.986744656939538167e-01,-9.039892931234433382e-01,-9.091679830905222692e-01,-9.142097557035306910e-01,-9.191138516900577704e-01,-9.238795325112867385e-01,-9.285060804732154782e-01,-9.329927988347388457e-01,-9.373390119125749598e-01,-9.415440651830208063e-01,-9.456073253805212797e-01,-9.495281805930366748e-01,-9.533060403541937511e-01,-9.569403357322089354e-01,-9.604305194155657865e-01,-9.637760657954398402e-01,-9.669764710448520706e-01,-9.700312531945439742e-01,-9.729399522055600658e-01,-9.757021300385285700e-01,-9.783173707196276547e-01,-9.807852804032304306e-01,-9.831054874312162850e-01,-9.852776423889412216e-01,-9.873014181578584347e-01,-9.891765099647810144e-01,-9.909026354277800097e-01,-9.924795345987099671e-01,-9.939069700023560605e-01,-9.951847266721968177e-01,-9.963126121827780013e-01,-9.972904566786902070e-01,-9.981181129001491792e-01,-9.987954562051724050e-01,-9.993223845883495438e-01,-9.996988186962042500e-01,-9.999247018391445030e-01,-1.000000000000000000e+00,-9.999247018391445030e-01,-9.996988186962042500e-01,-9.993223845883495438e-01,-9.987954562051724050e-01,-9.981181129001491792e-01,-9.972904566786902070e-01,-9.963126121827780013e-01,-9.951847266721969287e-01,-9.939069700023560605e-01,-9.924795345987099671e-01,-9.909026354277800097e-01,-9.891765099647810144e-01,-9.873014181578584347e-01,-9.852776423889412216e-01,-9.831054874312162850e-01,-9.807852804032304306e-01,-9.783173707196276547e-01,-9.757021300385285700e-01,-9.729399522055601768e-01,-9.700312531945439742e-01,-9.669764710448520706e-01,-9.637760657954398402e-01,-9.604305194155658976e-01,-9.569403357322089354e-01,-9.533060403541938621e-01,-9.495281805930366748e-01,-9.456073253805213907e-01,-9.415440651830208063e-01,-9.373390119125749598e-01,-9.329927988347388457e-01,-9.285060804732155892e-01,-9.238795325112867385e-01,-9.191138516900577704e-01,-9.142097557035306910e-01,-9.091679830905224913e-01,-9.039892931234434492e-01,-8.986744656939539277e-01,-8.932243011955152134e-01,-8.876396204028539350e-01,-8.819212643483550496e-01,-8.760700941954066012e-01,-8.700869911087114605e-01,-8.639728561215868075e-01,-8.577286100002721181e-01,-8.513551931052651955e-01,-8.448535652497072279e-01,-8.382247055548381898e-01,-8.314696123025454577e-01,-8.245893027850251800e-01,-8.175848131515837114e-01,-8.104571982525947682e-01,-8.032075314806449429e-01,-7.958369046088835663e-01,-7.883464276266063386e-01,-7.807372285720945992e-01,-7.730104533627371044e-01,-7.651672656224590696e-01,-7.572088465064846785e-01,-7.491363945234592592e-01,-7.409511253549589949e-01,-7.326542716724128157e-01,-7.242470829514668917e-01,-7.157308252838187057e-01,-7.071067811865475727e-01,-6.983762494089729156e-01,-6.895405447370670515e-01,-6.806009977954532442e-01,-6.715589548470185521e-01,-6.624157775901720058e-01,-6.531728429537766445e-01,-6.438315428897913861e-01,-6.343932841636454878e-01,-6.248594881423863434e-01,-6.152315905806269303e-01,-6.055110414043256561e-01,-5.956993044924334679e-01,-5.857978574564389751e-01,-5.758081914178454497e-01,-5.657318107836134535e-01,-5.555702330196021776e-01,-5.453249884220463528e-01,-5.349976198870971533e-01,-5.245896826784689493e-01,-5.141027441932217723e-01,-5.035383837257176864e-01,-4.928981922297841489e-01,-4.821837720791228854e-01,-4.713967368259978641e-01,-4.605387109582402272e-01,-4.496113296546068727e-01,-4.386162385385275475e-01,-4.275550934302820294e-01,-4.164295600976371525e-01,-4.052413140049899165e-01,-3.939920400610481543e-01,-3.826834323650898928e-01,-3.713171939518377096e-01,-3.598950365349883329e-01,-3.484186802494347868e-01,-3.368898533922203287e-01,-3.253102921622632593e-01,-3.136817403988914066e-01,-3.020059493192280287e-01,-2.902846772544623866e-01,-2.785196893850531707e-01,-2.667127574748984764e-01,-2.548656596045146827e-01,-2.429801799032640652e-01,-2.310581082806713316e-01,-2.191012401568700474e-01,-2.071113761922188379e-01,-1.950903220161286089e-01,-1.830398879551408953e-01,-1.709618887603012172e-01,-1.588581433338614735e-01,-1.467304744553618034e-01,-1.345807085071262788e-01,-1.224106751992163483e-01,-1.102222072938832398e-01,-9.801714032956082567e-02,-8.579731234444015753e-02,-7.356456359966773162e-02,-6.132073630220848809e-02,-4.906767432741796636e-02,-3.680722294135883171e-02,-2.454122852291232629e-02,-1.227153828572000692e-02,-0.000000000000000000e+00,-6.135884649154475269e-03,-1.227153828571992539e-02,-1.840672990580482019e-02,-2.454122852291228812e-02,-3.067480317663662595e-02,-3.680722294135883171e-02,-4.293825693494082024e-02,-4.906767432741801493e-02,-5.519524434968993420e-02,-6.132073630220857829e-02,-6.744391956366405094e-02,-7.356456359966742631e-02,-7.968243797143012563e-02,-8.579731234443989385e-02,-9.190895649713272386e-02,-9.801714032956060363e-02,-1.041216338720545864e-01,-1.102222072938830594e-01,-1.163186309119047523e-01,-1.224106751992161957e-01,-1.284981107937931688e-01,-1.345807085071261677e-01,-1.406582393328492109e-01,-1.467304744553617479e-01,-1.527971852584434354e-01,-1.588581433338614457e-01,-1.649131204899698944e-01,-1.709618887603012172e-01,-1.770042204121487495e-01,-1.830398879551409508e-01,-1.890686641498061926e-01,-1.950903220161282481e-01,-2.011046348420919005e-01,-2.071113761922185603e-01,-2.131103199160913619e-01,-2.191012401568697976e-01,-2.250839113597928320e-01,-2.310581082806711095e-01,-2.370236059943671980e-01,-2.429801799032638709e-01,-2.489276057457201485e-01,-2.548656596045145717e-01,-2.607941179152755140e-01,-2.667127574748983654e-01,-2.726213554499489766e-01,-2.785196893850530597e-01,-2.844075372112718769e-01,-2.902846772544623311e-01,-2.961508882436237888e-01,-3.020059493192280842e-01,-3.078496400415348666e-01,-3.136817403988915176e-01,-3.195020308160156919e-01,-3.253102921622629262e-01,-3.311063057598764292e-01,-3.368898533922200511e-01,-3.426607173119943783e-01,-3.484186802494345647e-01,-3.541635254204903438e-01,-3.598950365349881109e-01,-3.656129978047738538e-01,-3.713171939518375431e-01,-3.770074102164182595e-01,-3.826834323650897818e-01,-3.883450466988262462e-01,-3.939920400610480988e-01,-3.996241998456467881e-01,-4.052413140049898610e-01,-4.108431710579039109e-01,-4.164295600976371525e-01,-4.220002707997996816e-01,-4.275550934302820849e-01,-4.330938188531519573e-01,-4.386162385385276585e-01,-4.441221445704292003e-01,-4.496113296546065397e-01,-4.550835871263438359e-01,-4.605387109582400051e-01,-4.659764957679661812e-01,-4.713967368259976420e-01,-4.767992300633220881e-01,-4.821837720791227189e-01,-4.875501601484359959e-01,-4.928981922297840379e-01,-4.982276669727818685e-01,-5.035383837257175754e-01,-5.088301425431069891e-01,-5.141027441932216613e-01,-5.193559901655896427e-01,-5.245896826784689493e-01,-5.298036246862946053e-01,-5.349976198870971533e-01,-5.401714727298928542e-01,-5.453249884220464638e-01,-5.504579729366048113e-01,-5.555702330196021776e-01,-5.606615761973360312e-01,-5.657318107836131205e-01,-5.707807458869672557e-01,-5.758081914178453387e-01,-5.808139580957645265e-01,-5.857978574564388641e-01,-5.907597018588741644e-01,-5.956993044924333569e-01,-6.006164793838689731e-01,-6.055110414043255451e-01,-6.103828062763094753e-01,-6.152315905806268193e-01,-6.200572117632890956e-01,-6.248594881423863434e-01,-6.296382389149269843e-01,-6.343932841636454878e-01,-6.391244448637757314e-01,-6.438315428897913861e-01,-6.485144010221124411e-01,-6.531728429537767555e-01,-6.578066932970786374e-01,-6.624157775901717837e-01,-6.669999223036374714e-01,-6.715589548470183301e-01,-6.760927035753159231e-01,-6.806009977954530221e-01,-6.850836677727003554e-01,-6.895405447370668295e-01,-6.939714608896540016e-01,-6.983762494089729156e-01,-7.027547444572252999e-01,-7.071067811865474617e-01,-7.114321957452164336e-01,-7.157308252838185947e-01,-7.200025079613816548e-01,-7.242470829514668917e-01,-7.284643904482251964e-01,-7.326542716724128157e-01,-7.368165688773697930e-01,-7.409511253549591059e-01,-7.450577854414659473e-01,-7.491363945234592592e-01,-7.531867990436124094e-01,-7.572088465064844565e-01,-7.612023854842617787e-01,-7.651672656224589586e-01,-7.691033376455795878e-01,-7.730104533627369934e-01,-7.768884656732324423e-01,-7.807372285720943772e-01,-7.845565971555752416e-01,-7.883464276266062276e-01,-7.921065773002123889e-01,-7.958369046088834553e-01,-7.995372691079050131e-01,-8.032075314806448318e-01,-8.068475535437992230e-01,-8.104571982525947682e-01,-8.140363297059483028e-01,-8.175848131515837114e-01,-8.211025149911046483e-01,-8.245893027850252910e-01,-8.280450452577557963e-01,-8.314696123025452357e-01,-8.348628749863800103e-01,-8.382247055548379677e-01,-8.415549774368983327e-01,-8.448535652497070059e-01,-8.481203448032971215e-01,-8.513551931052651955e-01,-8.545579883654005338e-01,-8.577286100002721181e-01,-8.608669386377673094e-01,-8.639728561215866964e-01,-8.670462455156926485e-01,-8.700869911087113495e-01,-8.730949784182900908e-01,-8.760700941954066012e-01,-8.790122264286334142e-01,-8.819212643483549385e-01,-8.847970984309377895e-01,-8.876396204028539350e-01,-8.904487232447578782e-01,-8.932243011955153245e-01,-8.959662497561851069e-01,-8.986744656939538167e-01,-9.013488470460220281e-01,-9.039892931234433382e-01,-9.065957045149153348e-01,-9.091679830905222692e-01,-9.117060320054298783e-01,-9.142097557035306910e-01,-9.166790599210427049e-01,-9.191138516900577704e-01,-9.215140393420419018e-01,-9.238795325112867385e-01,-9.262102421383112683e-01,-9.285060804732154782e-01,-9.307669610789837122e-01,-9.329927988347388457e-01,-9.351835099389474992e-01,-9.373390119125749598e-01,-9.394592236021899190e-01,-9.415440651830208063e-01,-9.435934581619603856e-01,-9.456073253805212797e-01,-9.475855910177410912e-01,-9.495281805930366748e-01,-9.514350209690083382e-01,-9.533060403541937511e-01,-9.551411683057706714e-01,-9.569403357322089354e-01,-9.587034748958715991e-01,-9.604305194155657865e-01,-9.621214042690415802e-01,-9.637760657954398402e-01,-9.653944416976893983e-01,-9.669764710448520706e-01,-9.685220942744172667e-01,-9.700312531945439742e-01,-9.715038909862517835e-01,-9.729399522055600658e-01,-9.743393827855758582e-01,-9.757021300385285700e-01,-9.770281426577543948e-01,-9.783173707196276547e-01,-9.795697656854405189e-01,-9.807852804032304306e-01,-9.819638691095552430e-01,-9.831054874312162850e-01,-9.842100923869290252e-01,-9.852776423889412216e-01,-9.863080972445986694e-01,-9.873014181578584347e-01,-9.882575677307494644e-01,-9.891765099647810144e-01,-9.900582102622971226e-01,-9.909026354277800097e-01,-9.917097536690995252e-01,-9.924795345987099671e-01,-9.932119492347945000e-01,-9.939069700023560605e-01,-9.945645707342554154e-01,-9.951847266721968177e-01,-9.957674144676598171e-01,-9.963126121827780013e-01,-9.968202992911656679e-01,-9.972904566786902070e-01,-9.977230666441916362e-01,-9.981181129001491792e-01,-9.984755805732947742e-01,-9.987954562051724050e-01,-9.990777277526453615e-01,-9.993223845883495438e-01,-9.995294175010931426e-01,-9.996988186962042500e-01,-9.998305817958234032e-01,-9.999247018391445030e-01,-9.999811752826011091e-01,-0.000000000000000000e+00,-1.840672990580482019e-02,-3.680722294135883171e-02,-5.519524434968993420e-02,-7.356456359966742631e-02,-9.190895649713272386e-02,-1.102222072938830594e-01,-1.284981107937931688e-01,-1.467304744553617479e-01,-1.649131204899698944e-01,-1.830398879551409508e-01,-2.011046348420919005e-01,-2.191012401568697976e-01,-2.370236059943671980e-01,-2.548656596045145717e-01,-2.726213554499489766e-01,-2.902846772544623311e-01,-3.078496400415348666e-01,-3.253102921622629262e-01,-3.426607173119943783e-01,-3.598950365349881109e-01,-3.770074102164182595e-01,-3.939920400610480988e-01,-4.108431710579039109e-01,-4.275550934302820849e-01,-4.441221445704292003e-01,-4.605387109582400051e-01,-4.767992300633220881e-01,-4.928981922297840379e-01,-5.088301425431069891e-01,-5.245896826784689493e-01,-5.401714727298928542e-01,-5.555702330196021776e-01,-5.707807458869672557e-01,-5.857978574564388641e-01,-6.006164793838689731e-01,-6.152315905806268193e-01,-6.296382389149269843e-01,-6.438315428897913861e-01,-6.578066932970786374e-01,-6.715589548470183301e-01,-6.850836677727003554e-01,-6.983762494089729156e-01,-7.114321957452164336e-01,-7.242470829514668917e-01,-7.368165688773697930e-01,-7.491363945234592592e-01,-7.612023854842617787e-01,-7.730104533627369934e-01,-7.845565971555752416e-01,-7.958369046088834553e-01,-8.068475535437992230e-01,-8.175848131515837114e-01,-8.280450452577557963e-01,-8.382247055548379677e-01,-8.481203448032971215e-01,-8.577286100002721181e-01,-8.670462455156926485e-01,-8.760700941954066012e-01,-8.847970984309377895e-01,-8.932243011955153245e-01,-9.013488470460220281e-01,-9.091679830905222692e-01,-9.166790599210427049e-01,-9.238795325112867385e-01,-9.307669610789837122e-01,-9.373390119125749598e-01,-9.435934581619603856e-01,-9.495281805930366748e-01,-9.551411683057706714e-01,-9.604305194155657865e-01,-9.653944416976893983e-01,-9.700312531945439742e-01,-9.743393827855758582e-01,-9.783173707196276547e-01,-9.819638691095552430e-01,-9.852776423889412216e-01,-9.882575677307494644e-01,-9.909026354277800097e-01,-9.932119492347945000e-01,-9.951847266721968177e-01,-9.968202992911656679e-01,-9.981181129001491792e-01,-9.990777277526453615e-01,-9.996988186962042500e-01,-9.999811752826011091e-01,-9.999247018391445030e-01,-9.995294175010931426e-01,-9.987954562051724050e-01,-9.977230666441916362e-01,-9.963126121827780013e-01,-9.945645707342554154e-01,-9.924795345987099671e-01,-9.900582102622971226e-01,-9.873014181578584347e-01,-9.842100923869290252e-01,-9.807852804032304306e-01,-9.770281426577543948e-01,-9.729399522055601768e-01,-9.685220942744173778e-01,-9.637760657954398402e-01,-9.587034748958715991e-01,-9.533060403541938621e-01,-9.475855910177412023e-01,-9.415440651830208063e-01,-9.351835099389476103e-01,-9.285060804732155892e-01,-9.215140393420420128e-01,-9.142097557035306910e-01,-9.065957045149153348e-01,-8.986744656939539277e-01,-8.904487232447579892e-01,-8.819212643483550496e-01,-8.730949784182902018e-01,-8.639728561215868075e-01,-8.545579883654005338e-01,-8.448535652497072279e-01,-8.348628749863801213e-01,-8.245893027850251800e-01,-8.140363297059485248e-01,-8.032075314806449429e-01,-7.921065773002122778e-01,-7.807372285720945992e-01,-7.691033376455795878e-01,-7.572088465064846785e-01,-7.450577854414660584e-01,-7.326542716724128157e-01,-7.200025079613817658e-01,-7.071067811865475727e-01,-6.939714608896540016e-01,-6.806009977954532442e-01,-6.669999223036375824e-01,-6.531728429537766445e-01,-6.391244448637758424e-01,-6.248594881423863434e-01,-6.103828062763096973e-01,-5.956993044924334679e-01,-5.808139580957645265e-01,-5.657318107836134535e-01,-5.504579729366049223e-01,-5.349976198870971533e-01,-5.193559901655897537e-01,-5.035383837257176864e-01,-4.875501601484358849e-01,-4.713967368259978641e-01,-4.550835871263438914e-01,-4.386162385385275475e-01,-4.220002707997998481e-01,-4.052413140049899165e-01,-3.883450466988265792e-01,-3.713171939518377096e-01,-3.541635254204903993e-01,-3.368898533922203287e-01,-3.195020308160158029e-01,-3.020059493192280287e-01,-2.844075372112720990e-01,-2.667127574748984764e-01,-2.489276057457200930e-01,-2.310581082806713316e-01,-2.131103199160914174e-01,-1.950903220161286089e-01,-1.770042204121489438e-01,-1.588581433338614735e-01,-1.406582393328495439e-01,-1.224106751992163483e-01,-1.041216338720545725e-01,-8.579731234444015753e-02,-6.744391956366417584e-02,-4.906767432741796636e-02,-3.067480317663686534e-02,-1.227153828572000692e-02,6.135884649154554199e-03,2.454122852291207996e-02,4.293825693494077861e-02,6.132073630220824523e-02,7.968243797142994522e-02,9.801714032956058975e-02,1.163186309119044748e-01,1.345807085071260567e-01,1.527971852584434354e-01,1.709618887603009674e-01,1.890686641498061094e-01,2.071113761922185881e-01,2.250839113597926100e-01,2.429801799032638154e-01,2.607941179152756250e-01,2.785196893850528932e-01,2.961508882436237888e-01,3.136817403988911845e-01,3.311063057598762627e-01,3.484186802494345647e-01,3.656129978047735762e-01,3.826834323650896708e-01,3.996241998456468436e-01,4.164295600976369305e-01,4.330938188531518462e-01,4.496113296546066507e-01,4.659764957679659592e-01,4.821837720791226634e-01,4.982276669727815355e-01,5.141027441932215503e-01,5.298036246862946053e-01,5.453249884220461308e-01,5.606615761973359202e-01,5.758081914178453387e-01,5.907597018588739424e-01,6.055110414043254341e-01,6.200572117632892066e-01,6.343932841636452657e-01,6.485144010221123301e-01,6.624157775901717837e-01,6.760927035753158121e-01,6.895405447370668295e-01,7.027547444572250779e-01,7.157308252838184837e-01,7.284643904482251964e-01,7.409511253549588838e-01,7.531867990436124094e-01,7.651672656224589586e-01,7.768884656732325533e-01,7.883464276266058945e-01,7.995372691079047911e-01,8.104571982525946572e-01,8.211025149911046483e-01,8.314696123025452357e-01,8.415549774368985547e-01,8.513551931052648625e-01,8.608669386377670874e-01,8.700869911087113495e-01,8.790122264286334142e-01,8.876396204028540460e-01,8.959662497561848848e-01,9.039892931234431162e-01,9.117060320054297673e-01,9.191138516900576594e-01,9.262102421383113793e-01,9.329927988347389567e-01,9.394592236021896969e-01,9.456073253805211687e-01,9.514350209690083382e-01,9.569403357322088244e-01,9.621214042690415802e-01,9.669764710448521816e-01,9.715038909862516725e-01,9.757021300385284590e-01,9.795697656854405189e-01,9.831054874312162850e-01,9.863080972445986694e-01,9.891765099647809034e-01,9.917097536690995252e-01,9.939069700023560605e-01,9.957674144676598171e-01,9.972904566786902070e-01,9.984755805732947742e-01,9.993223845883494327e-01,9.998305817958234032e-01};
#pragma HLS ARRAY_RESHAPE variable=WR dim=1 factor=RAM_PART_FCT cyclic
#pragma HLS ARRAY_RESHAPE variable=WI dim=1 factor=RAM_PART_FCT cyclic

int ram_id = -1;
ap_uint<6> ram_addr = 0;

MYDTYPE xr[4][RAM_PART_FCT];
MYDTYPE xi[4][RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=xr dim=1 complete
#pragma HLS ARRAY_PARTITION variable=xr dim=2 complete
#pragma HLS ARRAY_PARTITION variable=xi dim=1 complete
#pragma HLS ARRAY_PARTITION variable=xi dim=2 complete

MYDTYPE yr[4][RAM_PART_FCT];
MYDTYPE yi[4][RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=yr dim=1 complete
#pragma HLS ARRAY_PARTITION variable=yr dim=2 complete
#pragma HLS ARRAY_PARTITION variable=yi dim=1 complete
#pragma HLS ARRAY_PARTITION variable=yi dim=2 complete

WTYPE wr[3][RAM_PART_FCT];
WTYPE wi[3][RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=wr dim=1 complete
#pragma HLS ARRAY_PARTITION variable=wr dim=2 complete
#pragma HLS ARRAY_PARTITION variable=wi dim=1 complete
#pragma HLS ARRAY_PARTITION variable=wi dim=2 complete

// 每循环读取4次数, 8次循环, 每次循环32个butterfly
for(int i = 0; i < 256/RAM_PART_FCT; i++) {
#pragma HLS PIPELINE ii=4

	// 读4次
	for(int j = 0; j < 4; j++) {
		for(int n = 0; n < RAM_PART_FCT; n++){
#pragma HLS UNROLL
			xr[j][n] = DTYPE2MYDTYPE(X_R[j*256+i*RAM_PART_FCT+n]);
			xi[j][n] = DTYPE2MYDTYPE(X_I[j*256+i*RAM_PART_FCT+n]);
		}
	}

	// 读入旋转因子
	for(int j = 0; j < 3; j++) {
		for(int n = 0; n < RAM_PART_FCT; n++){
#pragma HLS UNROLL
			wr[j][n] = WR[j*256+i*RAM_PART_FCT+n];
			wi[j][n] = WI[j*256+i*RAM_PART_FCT+n];
		}
	}


	// 基4 频率抽取 蝶形计算单元
	r4_dif_butterfly(xr, xi, wr, wi, yr, yi);


	// 4 cycle 写出结果
	for( int j = 0; j < 4; j++) {
		for(int n = 0; n < RAM_PART_FCT; n++) {
#pragma HLS UNROLL
			DOUTR[j*256+i*RAM_PART_FCT+n] = yr[j][n];
			DOUTI[j*256+i*RAM_PART_FCT+n] = yi[j][n];

			float y_flt = yr[j][n].to_float(); // for debug
		}
	}

}


}

void fft(DTYPE X_R[FFTSIZE], DTYPE X_I[FFTSIZE], DTYPE OUT_R[FFTSIZE], DTYPE OUT_I[FFTSIZE])
{
// 同时读入相邻的RAM_PART_FCT个数
#pragma HLS ARRAY_PARTITION variable=X_I dim=1 factor=RAM_PART_FCT/2 cyclic
#pragma HLS ARRAY_PARTITION variable=X_R dim=1 factor=RAM_PART_FCT/2 cyclic
#pragma HLS ARRAY_PARTITION variable=OUT_R dim=1 factor=RAM_PART_FCT/2 cyclic
#pragma HLS ARRAY_PARTITION variable=OUT_I dim=1 factor=RAM_PART_FCT/2 cyclic


#pragma HLS dataflow

	MYDTYPE Stage1_R[FFTSIZE], Stage1_I[FFTSIZE];
#pragma HLS ARRAY_RESHAPE variable=Stage1_R dim=1 factor=RAM_PART_FCT cyclic
#pragma HLS ARRAY_RESHAPE variable=Stage1_I dim=1 factor=RAM_PART_FCT cyclic

	MYDTYPE Stage2_R[FFTSIZE], Stage2_I[FFTSIZE];
#pragma HLS ARRAY_RESHAPE variable=Stage2_R dim=1 factor=RAM_PART_FCT cyclic
#pragma HLS ARRAY_RESHAPE variable=Stage2_I dim=1 factor=RAM_PART_FCT cyclic

	stream<ap_uint<1024>, 4> Stage3_R[RAM_PART_FCT2], Stage3_I[RAM_PART_FCT2];
#pragma HLS BIND_STORAGE variable=Stage3_R type=fifo
#pragma HLS BIND_STORAGE variable=Stage3_I type=fifo
#pragma HLS ARRAY_PARTITION variable=Stage3_R dim=1 complete
#pragma HLS ARRAY_PARTITION variable=Stage3_I dim=1 complete

	stream<ap_uint<1024>, 3> Stage4_R[RAM_PART_FCT2], Stage4_I[RAM_PART_FCT2];
#pragma HLS BIND_STORAGE variable=Stage4_R type=fifo
#pragma HLS BIND_STORAGE variable=Stage4_R type=fifo
#pragma HLS ARRAY_PARTITION variable=Stage4_R dim=1 complete
#pragma HLS ARRAY_PARTITION variable=Stage4_I dim=1 complete

	ap_uint<1024> Stage5_R[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT], Stage5_I[RAM_PART_FCT][FFTSIZE/RAM_PART_FCT/RAM_PART_FCT];
#pragma HLS ARRAY_PARTITION variable=Stage5_R dim=1 complete
#pragma HLS ARRAY_PARTITION variable=Stage5_I dim=1 complete

	fft_1(X_R, X_I, Stage1_R, Stage1_I);
	fft_2(Stage1_R, Stage1_I, Stage2_R, Stage2_I);
	fft_3(Stage2_R, Stage2_I, Stage3_R, Stage3_I);
	fft_4( Stage3_R, Stage3_I,  Stage4_R, Stage4_I);
	fft_5(Stage4_R, Stage4_I, Stage5_R, Stage5_I);
	bit_reverse(Stage5_R, Stage5_I, OUT_R, OUT_I);
//	out(Stage1_R, Stage1_I, OUT_R, OUT_I);

}













/*=======================END: FFT=========================*/




